import install from './install'
import createMatcher from './create-matcher'
import HashHistory from './history/hashhistory'
import HTML5History from './history/html5history'

// VueRouter 类
export default class VueRouter {
  // new VueRouter({ routes }) 创建时传入参数为对象
  constructor (options) {
    this._routes = options.routes || []
    // { match, addRoutes }
    // match => 根据路由地址返回路由规则
    // addRoutes => 动态添加路由规则
    this.matcher = createMatcher(this._routes)

    // 增加一个属性，记录所有 beforehooks 注册的钩子函数
    this.beforeHooks = []

    // 获取用户设置地模式 默认为hash
    const mode = this.mode = options.mode || 'hash'
    // 简单工厂设计模式 分类下载等
    switch (mode) {
      case 'hash':
        this.history = new HashHistory(this)
        break
      case 'history':
        this.history = new HTML5History(this)
        break
      default:
        throw new Error('mode error')
    }
  }

  // 定义 beforeEach 方法
  beforeEach (fn) {
    this.beforeHooks.push(fn)
  }

  // 初始化事件监听器，监视地址栏路由变化并切换相应组件
  // 改变url中的路由地址
  init (app) {
    // app 就是 Vue 的实例
    const history = this.history

    // 封装方法 保证this指向
    const setUpListener = () => {
      history.setUpListener()
    }
    // 当地址发生变化 执行的回调函数
    // 在回调中给 _route 重新赋值，更新视图
    history.listen(current => {
      // 响应式数据发生变化，重新渲染视图
      app._route = current
      // console.log(app._route)
    })

    // 第一次加载页面
    history.transitionTo(
      history.getCurrentLocation(),
      // 不能直接这么传递，他内部的this会有问题
      // history.setUpListener
      setUpListener
    )
  }
}

VueRouter.install = install
